package coc.core.collector;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

import coc.core.url.Url;

import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.NicelyResynchronizingAjaxController;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

import coo.base.exception.UncheckedException;

/**
 * 基于HtmlUnit的采集器。
 */
public class HtmlUnitCollector implements Collector {
	private WebClient webClient;
	private HtmlPage page;

	/**
	 * 构造方法。
	 * 
	 * @param conTimeout
	 *            超时时间
	 */
	public HtmlUnitCollector(Integer conTimeout) {
		this(conTimeout, BrowserVersion.getDefault());
	}

	/**
	 * 构造方法。
	 * 
	 * @param conTimeout
	 *            超时时间
	 * @param version
	 *            浏览器版本
	 */
	public HtmlUnitCollector(Integer conTimeout, BrowserVersion version) {
		webClient = new WebClient(version);
		webClient.setAjaxController(new NicelyResynchronizingAjaxController());
		setTimeout(conTimeout);
		webClient.getOptions().setJavaScriptEnabled(true);
		webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
		webClient.getOptions().setThrowExceptionOnScriptError(false);
		webClient.getOptions().setCssEnabled(false);
	}

	@Override
	public void collect(Url url) {
		try {
			page = webClient.getPage(url.toString());
		} catch (Exception e) {
			throw new UncheckedException("加载网页时发生异常:" + e.getMessage() + "["
					+ url + "]");
		}
	}

	@Override
	public void setTimeout(Integer timeout) {
		webClient.getOptions().setTimeout(timeout * 1000);
		webClient.setJavaScriptTimeout(timeout * 1000);
		webClient.waitForBackgroundJavaScript(timeout * 1000);
	}

	@Override
	public Document createDocument() {
		try {
			Document document = Jsoup.parse(page.asXml(), page.getUrl()
					.toExternalForm(), org.jsoup.parser.Parser.xmlParser());
			Elements baseElements = document.select("base[href]");
			if (!baseElements.isEmpty()) {
				String baseUri = baseElements.first().attr("href");
				document.setBaseUri(baseUri);
			}
			return document;
		} catch (Exception e) {
			throw new UncheckedException("加载网页时发生异常:" + e.getMessage() + "["
					+ page.getUrl().getPath() + "]");
		}
	}

	@Override
	public void destroy() {
		webClient.closeAllWindows();
		webClient = null;
	}

	public WebClient getWebClient() {
		return webClient;
	}

	public HtmlPage getPage() {
		return page;
	}

	public void setPage(HtmlPage page) {
		this.page = page;
	}
}
